package com.csci;

import java.util.HashMap;
import java.util.LinkedList;

public class Possibilities {
	

    public static enum Type {
           row, col, box;
   }
   public static LinkedList<Integer> getPossibilities(Sudoku s, int puzzleRow, int puzzleCol) {
           if(s.puzzleGrid[puzzleRow][puzzleCol] != -1){
                   return null;
           }
           
           Type t = getSmallestPossibilitySet(getPossileRowPossibilities(s, puzzleRow).size() , getPossibleColPossibilities(s, puzzleCol).size(), getPossibleBoxPossiblities(s, puzzleRow, puzzleCol).size()); 
           if(t == t.row){
                   return getPossileRowPossibilities(s, puzzleRow);
           }
           else if(t == t.col){
                   return getPossibleColPossibilities(s, puzzleCol);
           }
           else {
                   return getPossibleBoxPossiblities(s, puzzleRow, puzzleCol);
           }
   }

   public static LinkedList<Integer> getPossibilitiesBruteForce(Sudoku s, int row, int col) {
           LinkedList<Integer> cellSet = new LinkedList<Integer>();
           if(s.puzzleGrid[row][col] == -1){
                   for(int i = 1; i <= 9; i++){
                           cellSet.addFirst(i);
                   }
                   return cellSet;
           }
           else
                   return null;
           
   }
   
   public static LinkedList<Integer> getPossileRowPossibilities(Sudoku s, int puzzleRow) {
           HashMap<Integer, Boolean> temp = new HashMap<Integer, Boolean>();

           for (int possibleSolution = 1; possibleSolution <= 9; possibleSolution++) {
                   temp.put(possibleSolution, true);
           }

           for (int col = 0; col < s.dimension; col++) {
                   if (s.puzzleGrid[puzzleRow][col] != -1) {
                           temp.remove(s.puzzleGrid[puzzleRow][col]);
                   }
           }

           LinkedList<Integer> cellSet = new LinkedList<Integer>();
           for (Integer possibleSolution : temp.keySet()) {
                   cellSet.addFirst(possibleSolution);
           }

           return cellSet;
   }

   public static LinkedList<Integer> getPossibleColPossibilities(Sudoku s, int puzzleCol) {

           HashMap<Integer, Boolean> temp = new HashMap<Integer, Boolean>();

           for (int possibleSolution = 1; possibleSolution <= 9; possibleSolution++) {
                   temp.put(possibleSolution, true);
           }

           for (int row = 0; row < s.dimension; row++) {
                   if (s.puzzleGrid[row][puzzleCol] != -1) {
                           temp.remove(s.puzzleGrid[row][puzzleCol]);
                   }
           }

           LinkedList<Integer> cellSet = new LinkedList<Integer>();
           for (Integer possibleSolution : temp.keySet()) {
                   cellSet.addFirst(possibleSolution);
           }

           return cellSet;
   }
   
   
   public static LinkedList<Integer> getPossibleBoxPossiblities (Sudoku s, int puzzleRow, int puzzleCol) {
           PuzzleBox pb = convertTileToBox(puzzleRow, puzzleCol);
           
           HashMap<Integer, Boolean> temp = new HashMap<Integer, Boolean>();

           for (int possibleSolution = 1; possibleSolution <= 9; possibleSolution++) {
                   temp.put(possibleSolution, true);
           }

           for (int row = pb.rowStart; row < pb.rowStop; row++) {
                   for(int col = pb.colStart; col < pb.colStop; col++){
                           if (s.puzzleGrid[row][col] != -1) {
                                   temp.remove(s.puzzleGrid[row][col]);
                           }
                   }
           }
           LinkedList<Integer> cellSet = new LinkedList<Integer>();
           for (Integer possibleSolution : temp.keySet()) {
                   cellSet.addFirst(possibleSolution);
           }

           return cellSet;
   }
   
   public static Type getSmallestPossibilitySet(int rowPossiblites, int colPossiblities, int boxPossiblities){
           if(rowPossiblites <= colPossiblities){
                   if(rowPossiblites <= boxPossiblities){
                                   return Type.row;
                           }
                           else{
                                   return Type.box;
                           }
           }
           else if(colPossiblities <= boxPossiblities){
                   return Type.col;
           }
           else{
                   return Type.box;
           }
   }
   
   
   public static PuzzleBox convertTileToBox(int puzzleRow, int puzzleCol) {
           
           int rowStart;
           int rowStop;
           int colStart;
           int colStop;
           if(puzzleRow <3){
                   rowStart = 0;
                   rowStop = 3;
           }
           else if(puzzleRow>= 3 && puzzleRow < 6){
                   rowStart = 3;
                   rowStop = 6;
           }
           else {
                   rowStart = 6;
                   rowStop = 9;
           }
           
           
           if(puzzleCol < 3){
                   colStart = 0;
                   colStop = 3;
           }
           else if(puzzleCol>= 3 && puzzleCol < 6){
                   colStart = 3;
                   colStop = 6;
           }
           else {
                   colStart = 6;
                   colStop = 9;
           }
           return new PuzzleBox(rowStart, rowStop, colStart, colStop);
   }
     
}
